using CollabApp.Application.Interfaces;
using CollabApp.Application.DTOs.Game;
using CollabApp.Domain.ValueObjects;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using CollabApp.API.Common;
using Microsoft.AspNetCore.SignalR;
using CollabApp.API.Hubs;

namespace CollabApp.API.Controllers
{
    /// <summary>
    /// 画线圈地游戏控制器
    /// 处理游戏的创建、加入、开始等HTTP请求
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    [Authorize]
    public class LineDrawingGameController : ControllerBase
    {
        private readonly ILineDrawingGameService _gameService;
        private readonly IHubContext<LineDrawingGameHub> _hubContext;
        private readonly ILogger<LineDrawingGameController> _logger;

        public LineDrawingGameController(
            ILineDrawingGameService gameService,
            IHubContext<LineDrawingGameHub> hubContext,
            ILogger<LineDrawingGameController> logger)
        {
            _gameService = gameService;
            _hubContext = hubContext;
            _logger = logger;
        }

        /// <summary>
        /// 创建游戏
        /// </summary>
        /// <param name="request">创建游戏请求</param>
        /// <returns>创建结果</returns>
        [HttpPost("create")]
        public async Task<IActionResult> CreateGame([FromBody] CreateGameRequest request)
        {
            try
            {
                var userId = GetCurrentUserId();
                var userName = GetCurrentUserName();

                var settings = new GameSettings
                {
                    Duration = request.GameTimeMinutes * 60,
                    MapWidth = 1000,
                    MapHeight = 1000,
                    MaxPlayers = request.MaxPlayers,
                    EnablePowerUps = true,
                    EnableSpecialEvents = true,
                    GameMode = "classic"
                };

                var result = await _gameService.CreateGameAsync(request.RoomId.ToString(), settings, userId, userName);

                if (result.Success)
                {
                    _logger.LogInformation("游戏创建成功: GameId={GameId}, Host={HostName}", result.GameId, userName);
                    
                    return Ok(ApiResponse<object>.CreateSuccess(new
                    {
                        gameId = result.GameId,
                        roomId = request.RoomId,
                        status = result.GameState?.Status ?? "preparing",
                        settings = new
                        {
                            maxPlayers = settings.MaxPlayers,
                            minPlayersToStart = 2,
                            gameDuration = $"{settings.Duration / 60}分钟",
                            mapConfiguration = new
                            {
                                width = settings.MapWidth,
                                height = settings.MapHeight,
                                shape = "circle"
                            }
                        },
                        createdAt = DateTime.UtcNow,
                        joinUrl = $"/game/{result.GameId}/join"
                    }, "游戏创建成功"));
                }
                else
                {
                    return BadRequest(ApiResponse<object>.CreateFailure("创建游戏失败", result.Errors));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建游戏时发生错误");
                return StatusCode(500, ApiResponse<object>.CreateError("创建游戏失败", new[] { "服务器错误" }.ToList()));
            }
        }

        /// <summary>
        /// 加入游戏
        /// </summary>
        /// <param name="request">加入游戏请求</param>
        /// <returns>加入结果</returns>
        [HttpPost("join")]
        public async Task<IActionResult> JoinGame([FromBody] JoinGameRequest request)
        {
            try
            {
                var userId = GetCurrentUserId();
                var userName = request.PlayerName ?? GetCurrentUserName();

                var result = await _gameService.JoinGameAsync(request.GameId.ToString(), userId, userName);

                if (result.Success)
                {
                    _logger.LogInformation("玩家加入游戏: GameId={GameId}, Player={PlayerName}", request.GameId, userName);

                    // 广播玩家加入事件
                    await _hubContext.Clients.Group($"Game_{request.GameId}").SendAsync("PlayerJoined", new
                    {
                        PlayerId = userId,
                        Username = userName,
                        PlayerColor = result.PlayerState?.Color ?? "#FF0000",
                        IsRejoining = result.IsRejoining,
                        TotalPlayers = result.GameState?.Players.Count ?? 0
                    });

                    var messages = new List<string>
                    {
                        "🎉 成功加入游戏！",
                        $"🎨 您的颜色是 {result.PlayerState?.Color ?? "红色"}",
                        $"📍 出生位置: ({result.PlayerState?.CurrentPosition.X ?? 0}, {result.PlayerState?.CurrentPosition.Y ?? 0})",
                        $"👥 当前房间人数: {result.GameState?.Players.Count ?? 0}/{result.GameState?.MaxPlayers ?? 8}"
                    };

                    return Ok(ApiResponse<object>.CreateSuccess(new
                    {
                        playerId = userId,
                        playerName = userName,
                        playerColor = result.PlayerState?.Color ?? "#FF0000",
                        currentPosition = new { x = result.PlayerState?.CurrentPosition.X ?? 0, y = result.PlayerState?.CurrentPosition.Y ?? 0 },
                        state = result.PlayerState?.IsAlive == true ? "Idle" : "Dead",
                        totalTerritoryArea = result.PlayerState?.TotalTerritoryArea ?? 0,
                        inventory = new string[0]
                    }, messages));
                }
                else
                {
                    return BadRequest(ApiResponse<object>.CreateFailure("加入游戏失败", result.Errors));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "加入游戏时发生错误");
                return StatusCode(500, ApiResponse<object>.CreateError("加入游戏失败", new[] { "服务器错误" }.ToList()));
            }
        }

        /// <summary>
        /// 开始游戏
        /// </summary>
        /// <param name="gameId">游戏ID</param>
        /// <returns>开始结果</returns>
        [HttpPost("{gameId}/start")]
        public async Task<IActionResult> StartGame(Guid gameId)
        {
            try
            {
                var userId = GetCurrentUserId();
                var result = await _gameService.StartGameAsync(gameId, userId);

                if (result.Success)
                {
                    _logger.LogInformation("游戏开始: GameId={GameId}", gameId);

                    // 广播游戏开始事件
                    await _hubContext.Clients.Group($"Game_{gameId}").SendAsync("GameStarted", new
                    {
                        GameId = gameId,
                        Status = "playing",
                        StartTime = result.StartTime,
                        Duration = result.Duration,
                        Players = result.GameState?.Players.Select(p => new
                        {
                            PlayerId = p.PlayerId,
                            Username = p.Username,
                            Color = p.Color,
                            Position = new { X = p.CurrentPosition.X, Y = p.CurrentPosition.Y },
                            IsAlive = p.IsAlive
                        }).ToArray()
                    });

                    return Ok(ApiResponse<object>.CreateSuccess(new
                    {
                        gameId = gameId,
                        status = "playing",
                        startTime = result.StartTime,
                        duration = result.Duration
                    }, "游戏开始成功"));
                }
                else
                {
                    return BadRequest(ApiResponse<object>.CreateFailure("开始游戏失败", result.Errors));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "开始游戏时发生错误: GameId={GameId}", gameId);
                return StatusCode(500, ApiResponse<object>.CreateError("开始游戏失败", new[] { "服务器错误" }.ToList()));
            }
        }

        /// <summary>
        /// 获取游戏状态
        /// </summary>
        /// <param name="gameId">游戏ID</param>
        /// <returns>游戏状态</returns>
        [HttpGet("{gameId}/state")]
        public async Task<IActionResult> GetGameState(Guid gameId)
        {
            try
            {
                var gameState = await _gameService.GetGameStateAsync(gameId);
                if (gameState == null)
                {
                    return NotFound(ApiResponse<LineDrawingGameState>.CreateNotFound("游戏不存在"));
                }

                return Ok(ApiResponse<LineDrawingGameState>.CreateSuccess(gameState));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取游戏状态时发生错误: GameId={GameId}", gameId);
                return StatusCode(500, ApiResponse<LineDrawingGameState>.CreateError("获取游戏状态失败", new[] { "服务器错误" }.ToList()));
            }
        }

        /// <summary>
        /// 获取游戏排行榜
        /// </summary>
        /// <param name="gameId">游戏ID</param>
        /// <returns>排行榜</returns>
        [HttpGet("{gameId}/ranking")]
        public async Task<IActionResult> GetGameRanking(Guid gameId)
        {
            try
            {
                var rankings = await _gameService.GetRealTimeRankingAsync(gameId);
                return Ok(ApiResponse<List<PlayerRankingDto>>.CreateSuccess(rankings));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取游戏排行榜时发生错误: GameId={GameId}", gameId);
                return StatusCode(500, ApiResponse<List<PlayerRankingDto>>.CreateError("获取排行榜失败", new[] { "服务器错误" }.ToList()));
            }
        }

        /// <summary>
        /// 离开游戏
        /// </summary>
        /// <param name="gameId">游戏ID</param>
        /// <returns>离开结果</returns>
        [HttpPost("{gameId}/leave")]
        public async Task<IActionResult> LeaveGame(Guid gameId)
        {
            try
            {
                var userId = GetCurrentUserId();
                var userName = GetCurrentUserName();

                var result = await _gameService.LeaveGameAsync(gameId, userId);

                if (result.Success)
                {
                    _logger.LogInformation("玩家离开游戏: GameId={GameId}, Player={PlayerName}", gameId, userName);

                    // 广播玩家离开事件
                    await _hubContext.Clients.Group($"Game_{gameId}").SendAsync("PlayerLeft", new
                    {
                        PlayerId = userId,
                        Username = userName,
                        RemainingPlayerCount = result.RemainingPlayerCount
                    });

                    return Ok(ApiResponse<object>.CreateSuccess(new
                    {
                        remainingPlayerCount = result.RemainingPlayerCount
                    }, "离开游戏成功"));
                }
                else
                {
                    return BadRequest(ApiResponse<object>.CreateFailure("离开游戏失败", result.Errors));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "离开游戏时发生错误: GameId={GameId}", gameId);
                return StatusCode(500, ApiResponse<object>.CreateError("离开游戏失败", new[] { "服务器错误" }.ToList()));
            }
        }

        /// <summary>
        /// 玩家移动（HTTP版本，主要用于测试）
        /// </summary>
        /// <param name="request">移动请求</param>
        /// <returns>移动结果</returns>
        [HttpPost("move")]
        public async Task<IActionResult> PlayerMove([FromBody] PlayerMoveRequest request)
        {
            try
            {
                var userId = GetCurrentUserId();
                var result = await _gameService.ProcessPlayerMoveAsync(
                    request.GameId, userId, 
                    new CollabApp.Domain.ValueObjects.Position(request.X, request.Y), 
                    DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());

                if (result.Success)
                {
                    // 通过SignalR广播移动
                    await _hubContext.Clients.Group($"Game_{request.GameId}").SendAsync("PlayerMoved", new
                    {
                        PlayerId = userId,
                        Position = new { X = request.X, Y = request.Y },
                        MovementSpeed = result.MovementSpeed,
                        IsInEnemyTerritory = result.IsInEnemyTerritory,
                        Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                    });

                    return Ok(ApiResponse<LineDrawingMoveResult>.CreateSuccess(result));
                }
                else
                {
                    return BadRequest(ApiResponse<LineDrawingMoveResult>.CreateFailure("移动失败", result.Errors));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理玩家移动时发生错误");
                return StatusCode(500, ApiResponse<LineDrawingMoveResult>.CreateError("移动失败", new[] { "服务器错误" }.ToList()));
            }
        }

        /// <summary>
        /// 使用道具
        /// </summary>
        /// <param name="request">使用道具请求</param>
        /// <returns>使用结果</returns>
        [HttpPost("use-item")]
        public async Task<IActionResult> UseItem([FromBody] UseItemRequest request)
        {
            try
            {
                var userId = GetCurrentUserId();
                var result = await _gameService.UsePowerUpAsync(
                    request.GameId, userId, request.ItemType, 
                    DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());

                if (result.Success)
                {
                    // 广播道具使用事件
                    await _hubContext.Clients.Group($"Game_{request.GameId}").SendAsync("PowerUpUsed", new
                    {
                        PlayerId = userId,
                        PowerUpType = request.ItemType,
                        Effect = result.Effect,
                        DurationMs = result.DurationMs,
                        EffectParameters = result.EffectParameters,
                        TargetX = request.TargetX,
                        TargetY = request.TargetY,
                        Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                    });

                    return Ok(ApiResponse<PowerUpUseResult>.CreateSuccess(result));
                }
                else
                {
                    return BadRequest(ApiResponse<PowerUpUseResult>.CreateFailure("使用道具失败", result.Errors));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "使用道具时发生错误");
                return StatusCode(500, ApiResponse<PowerUpUseResult>.CreateError("使用道具失败", new[] { "服务器错误" }.ToList()));
            }
        }

        // 辅助方法
        private Guid GetCurrentUserId()
        {
            var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (Guid.TryParse(userIdClaim, out var userId))
            {
                return userId;
            }
            throw new UnauthorizedAccessException("无效的用户认证");
        }

        private string GetCurrentUserName()
        {
            return User.FindFirst(ClaimTypes.Name)?.Value ?? "Unknown";
        }
    }

    // 请求DTO类
    public class CreateGameRequest
    {
        public Guid RoomId { get; set; }
        public int MaxPlayers { get; set; } = 6;
        public int GameTimeMinutes { get; set; } = 5;
    }

    public class JoinGameRequest
    {
        public Guid GameId { get; set; }
        public string? PlayerName { get; set; }
    }

    public class PlayerMoveRequest
    {
        public Guid GameId { get; set; }
        public float X { get; set; }
        public float Y { get; set; }
        public bool IsDrawing { get; set; }
        public string? Timestamp { get; set; }
    }

    public class UseItemRequest
    {
        public Guid GameId { get; set; }
        public PowerUpType ItemType { get; set; }
        public float? TargetX { get; set; }
        public float? TargetY { get; set; }
    }
}